<template>
  <div class="l-rblock">
    <div v-show="steps(0)" class="l-rblock" style="padding:24px;">
      <div class="l-page-panel">
        <el-form
          :model="formData"
          :rules="rules"
          size="mini"
          ref="baseInfo"
          label-width="88px"
        >
          <el-col :span="24">
            <el-form-item :label="$t('名称')" prop="f_Name">
              <el-input v-model="formData.f_Name"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item :label="$t('分类')" prop="f_Category">
              <l-tree-select
                v-model="formData.f_Category"
                :placeholder="$t('请选择')"
                :options="lr_dataItemTree(lr_dataItem['FormSort'])"
              >
              </l-tree-select>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item :label="$t('数据库')" prop="f_DbCode">
              <el-select
                v-model="formData.f_DbCode"
                :placeholder="$t('请选择')"
              >
                <el-option-group
                  v-for="group in lr_dblinkTree"
                  :key="group.id"
                  :label="group.label"
                >
                  <el-option
                    v-for="item in group.children"
                    :key="item.id"
                    :label="item.label"
                    :value="item.id"
                  >
                  </el-option>
                </el-option-group>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item :label="$t('状态')" prop="f_EnabledMark">
              <el-switch
                :active-value="1"
                :inactive-value="0"
                v-model="formData.f_EnabledMark"
              >
              </el-switch>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item :label="$t('类型')" prop="f_FormType">
              <l-radio
                :options="[
                  { value: 0, label: $t('常规表单') },
                  { value: 1, label: $t('视图表单') },
                  { value: 2, label: $t('自动建表') },
                ]"
                v-model="formData.f_FormType"
                :disabled="isDisabled"
                @change="handleFormTypeChange"
              >
              </l-radio>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item :label="$t('描述')" prop="f_Description">
              <el-input
                type="textarea"
                v-model="formData.f_Description"
              ></el-input>
            </el-form-item>
          </el-col>
        </el-form>
        <template v-if="formData.f_FormType == 0">
          <el-col :span="24">
            <div class="l-title">
              {{ $t("添加数据库表（请先选择数据库）") }}
            </div>
          </el-col>
          <el-col :key="1" :span="24">
            <l-edit-table
              addBtnText="添加"
              :dataSource="dbTableData"
              @addRow="addRow"
              @deleteRow="deleteRow"
            >
              <el-table-column
                prop="type"
                :label="$t('类别')"
                width="64"
                align="center"
              >
                <template slot-scope="scope">
                  <el-tag v-if="scope.row.type == 'main'" size="mini"
                    >主表</el-tag
                  >
                  <el-tag
                    @click="chlidTagClick(scope.row)"
                    v-else
                    size="mini"
                    style="cursor: pointer;"
                    type="warning"
                    >子表</el-tag
                  >
                </template>
              </el-table-column>
              <el-table-column prop="name" :label="$t('表名')" minWidth="100">
              </el-table-column>
              <el-table-column prop="field" :label="$t('外键')" minWidth="100">
                <template v-if="scope.row.type != 'main'" slot-scope="scope">
                  <el-select
                    size="mini"
                    v-model="scope.row.field"
                    :placeholder="$t('请选择')"
                  >
                    <el-option
                      v-for="item in scope.row.columns || []"
                      :key="item.name"
                      :label="item.name"
                      :value="item.name"
                    >
                    </el-option>
                  </el-select>
                </template>
              </el-table-column>
              <el-table-column
                prop="relationName"
                :label="$t('关联表')"
                minWidth="100"
              >
                <template v-if="scope.row.type != 'main'" slot-scope="scope">
                  <el-select
                    size="mini"
                    v-model="scope.row.relationName"
                    :placeholder="$t('请选择')"
                  >
                    <el-option
                      v-for="item in relationTables(scope.row.name)"
                      :key="item.name"
                      :label="item.name"
                      :value="item.name"
                    >
                    </el-option>
                  </el-select>
                </template>
              </el-table-column>
              <el-table-column
                prop="relationField"
                :label="$t('关联主键')"
                minWidth="100"
              >
                <template
                  v-if="scope.row.type != 'main' && scope.row.relationName"
                  slot-scope="scope"
                >
                  <el-select
                    size="mini"
                    v-model="scope.row.relationField"
                    :placeholder="$t('请选择')"
                  >
                    <el-option
                      v-for="item in relationTableFields(
                        scope.row.relationName
                      )"
                      :key="item.name"
                      :label="item.name"
                      :value="item.name"
                    >
                    </el-option>
                  </el-select>
                </template>
              </el-table-column>
            </l-edit-table>
          </el-col>
          <el-col :span="24">
            <div class="l-title">
              {{
                $t("添加数据库关联表，只用来做数据权限设置（请先选择数据库）")
              }}
            </div>
          </el-col>
          <el-col :key="2" :span="24">
            <l-edit-table
              addBtnText="添加"
              :dataSource="dbTableRData"
              @addRow="addDbTableRData"
              @deleteRow="deleteDbTableRData"
            >
              <el-table-column prop="fname" :label="$t('名称')" minWidth="160">
                <template slot-scope="scope">
                  <el-input size="mini" v-model="scope.row.fname"></el-input>
                </template>
              </el-table-column>
              <el-table-column prop="name" :label="$t('表名')" minWidth="160">
              </el-table-column>
              <el-table-column
                prop="cfield"
                :label="$t('比较字段')"
                minWidth="160"
              >
                <template slot-scope="scope">
                  <el-select
                    size="mini"
                    v-model="scope.row.cfield"
                    :placeholder="$t('请选择')"
                  >
                    <el-option
                      v-for="item in scope.row.columns || []"
                      :key="item.name"
                      :label="item.name"
                      :value="item.name"
                    >
                    </el-option>
                  </el-select>
                </template>
              </el-table-column>
              <el-table-column prop="field" :label="$t('外键')" minWidth="160">
                <template slot-scope="scope">
                  <el-select
                    size="mini"
                    v-model="scope.row.field"
                    :placeholder="$t('请选择')"
                  >
                    <el-option
                      v-for="item in scope.row.columns || []"
                      :key="item.name"
                      :label="item.name"
                      :value="item.name"
                    >
                    </el-option>
                  </el-select>
                </template>
              </el-table-column>
              <el-table-column
                prop="relationName"
                :label="$t('关联表')"
                minWidth="160"
              >
                <template v-if="scope.row.type != 'main'" slot-scope="scope">
                  <el-select
                    size="mini"
                    v-model="scope.row.relationName"
                    :placeholder="$t('请选择')"
                  >
                    <el-option
                      v-for="item in dbTableData"
                      :key="item.name"
                      :label="item.name"
                      :value="item.name"
                    >
                    </el-option>
                  </el-select>
                </template>
              </el-table-column>
              <el-table-column
                prop="relationField"
                :label="$t('关联主键')"
                minWidth="160"
              >
                <template v-if="scope.row.relationName" slot-scope="scope">
                  <el-select
                    size="mini"
                    v-model="scope.row.relationField"
                    :placeholder="$t('请选择')"
                  >
                    <el-option
                      v-for="item in relationTableFields(
                        scope.row.relationName
                      )"
                      :key="item.name"
                      :label="item.name"
                      :value="item.name"
                    >
                    </el-option>
                  </el-select>
                </template>
              </el-table-column>
            </l-edit-table>
          </el-col>
        </template>
        <template v-if="formData.f_FormType == 1">
          <el-col :span="24">
            <div class="l-title">
              {{ $t("添加数据视图（请先选择数据库）") }}
            </div>
          </el-col>
          <el-col :span="24">
            <l-edit-table
              addBtnText="添加"
              :dataSource="dbTableData"
              @addRow="addSqlData"
              @deleteRow="deleteSqlData"
            >
              <el-table-column
                prop="type"
                :label="$t('类别')"
                width="64"
                align="center"
              >
                <template slot-scope="scope">
                  <el-tag v-if="scope.row.type == 'main'" size="mini"
                    >主</el-tag
                  >
                  <el-tag v-else size="mini" type="warning">子</el-tag>
                </template>
              </el-table-column>
              <el-table-column prop="name" :label="$t('名称')" minWidth="160">
                <el-button
                  type="text"
                  slot-scope="scope"
                  @click.stop="editSqlData(scope.row)"
                  >{{ scope.row.name }}</el-button
                >
              </el-table-column>
              <el-table-column
                prop="relationField"
                :label="$t('关联字段')"
                minWidth="160"
              >
                <el-select
                  v-if="scope.row.type != 'main'"
                  slot-scope="scope"
                  size="mini"
                  v-model="scope.row.relationField"
                  placeholder="请选择"
                >
                  <el-option
                    v-for="item in sqlMainCols || []"
                    :key="item.name"
                    :label="item.name"
                    :value="item.name"
                  >
                  </el-option>
                </el-select>
              </el-table-column>
            </l-edit-table>
          </el-col>
        </template>
      </div>
    </div>
    <div v-show="steps(1)" class="l-rblock">
      <l-form-design
        :dbTables="dbTableData"
        :isAutoCreateTable="formData.f_FormType == 2"
        ref="formDesign"
      ></l-form-design>
    </div>
    <l-codetable-selectdialog
      :visible.sync="dbtableSelectdialog"
      :dbCode="formData.f_DbCode"
      @select="dbSelect"
    >
    </l-codetable-selectdialog>

    <l-dialog
      :title="sqlDialogTitle"
      :visible.sync="addSqlDialog"
      :width="640"
      @ok="sqlDialogSave"
      @closed="sqlDialogClosed"
      @opened="sqlDialogOpened"
    >
      <sql-form ref="sqlForm"></sql-form>
    </l-dialog>
  </div>
</template>
<script>
const apiScheme = window.$api.custmerForm.scheme;
const apiCodeTable = window.$api.data.codeTable;

import SqlForm from "./sqlForm.vue";
export default {
  props: {
    stepActive: {
      type: Number,
      default: 0,
    },
    isDisabled: {
      type: Boolean,
      default: false,
    },
  },
  components: {
    SqlForm,
  },
  data() {
    return {
      formData: {
        f_Name: "",
        f_Category: "",
        f_DbCode: "",
        f_EnabledMark: 1,
        f_FormType: 0,
        f_Description: "",
      },
      rules: {
        f_Name: [
          { required: true, message: this.$t("请输入"), trigger: "blur" },
        ],
        f_Category: [
          { required: true, message: this.$t("请选择"), trigger: "change" },
        ],
        f_DbCode: [
          { required: true, message: this.$t("请选择"), trigger: "change" },
        ],
      },
      dbTableData: [],
      dbtableSelectdialog: false,

      dbTableRData: [], // 关联表数据用于数据权限
      isAddDbTableRData: false,

      addSqlDialog: false,
      editSql: false,
      sqlDialogTitle: "",
      sqlDialogRow: null,

      isNotFetchTables: false,
      tableColumns: {}, // 缓存列信息
      mainTableName: "",
    };
  },
  created() {
    this.initData();
  },
  computed: {
    sqlMainCols() {
      const table = this.dbTableData.find((t) => t.type == "main");
      return table.columns;
    },
  },
  methods: {
    initData() {
      this.lr_loadDblink();
    },
    async dbSelect(list, showLoading, hideLoading) {
      showLoading();
      const tableList = [];
      const notAddTable = [];
      list.forEach((item) => {
        const table = {
          id: item.f_TableName,
          name: item.f_TableName,
          comment: item.f_Description,
          columns: [],
        };
        // 加载表的列信息
        if (this.tableColumns[table.name]) {
          table.columns = this.tableColumns[table.name];
        } else {
          tableList.push(table);
        }

        if (this.isAddDbTableRData) {
          if (
            this.dbTableData.find((t) => {
              return t.name == table.name;
            }) == undefined
          ) {
            this.dbTableRData.push(table);
          } else {
            notAddTable.push(table.name);
          }
        } else {
          if (this.dbTableData.length == 0) {
            table.type = "main";
            this.dbTableData.push(table);
          } else if (
            this.dbTableData.find((t) => {
              return t.name == table.name;
            }) == undefined
          ) {
            table.type = "chlid";
            this.dbTableData.push(table);
          } else {
            notAddTable.push(table.name);
          }
        }
      });

      if (tableList.length > 0) {
        const codeTables = await this.$awaitWraper(
          apiCodeTable.getList(
            this.formData.f_DbCode,
            String(tableList.map((t) => t.name))
          )
        );
        for (const tableItem of tableList) {
          const codeTable = codeTables.find(
            (t) => t.lr_db_codetableEntity.f_TableName == tableItem.name
          );
          tableItem.columns = codeTable.lr_db_codecolumnsList.map((t) => ({
            name: t.f_DbColumnName,
            csType: t.f_CsType,
            isIdentity: t.f_IsIdentity == 1,
            isPrimary: t.f_IsPrimaryKey == 1,
            isNullable: t.f_IsNullable == 1,
            coment: t.f_Description,
          }));

          this.tableColumns[tableItem.name] = tableItem.columns;
        }
      }

      if (notAddTable.length > 0) {
        if (this.isAddDbTableRData) {
          this.$message({
            message: `不能是表单已经绑定的表【${String(notAddTable)}】`,
            type: "warning",
          });
        } else {
          this.$message({
            message: `重复添加表【${String(notAddTable)}】`,
            type: "warning",
          });
        }
      }

      this.dbtableSelectdialog = false;
      this.isNotFetchTables = false;
      hideLoading();
    },
    chlidTagClick(row) {
      this.dbTableData.find((t) => {
        return t.type == "main";
      }).type = "chlid";
      row.type = "main";
      this.$set(this.dbTableData, 0, this.dbTableData[0]);
    },
    addRow() {
      this.isAddDbTableRData = false;
      if (this.formData.f_DbCode) {
        this.dbtableSelectdialog = true;
      } else {
        this.$message({
          message: "请选择数据库",
          type: "warning",
        });
      }
    },
    deleteRow(data) {
      this.dbTableData.splice(data.index, 1);
      if (data.row.type == "main" && this.dbTableData.length > 0) {
        this.dbTableData[0].type = "main";
        this.dbTableData[0].relationName = "";
        this.dbTableData[0].relationField = "";
        this.dbTableData[0].field = "";
        this.$set(this.dbTableData, 0, this.dbTableData[0]);
      }
    },
    relationTables(myName) {
      let list = [];
      this.dbTableData.forEach((item) => {
        if (item.name != myName) {
          list.push(item);
        }
      });
      return list;
    },
    relationTableFields(tableName) {
      const table =
        this.dbTableData.find((t) => {
          return t.name == tableName;
        }) || {};
      return table.columns || [];
    },

    addDbTableRData() {
      this.isAddDbTableRData = true;
      if (this.formData.f_DbCode) {
        this.dbtableSelectdialog = true;
      } else {
        this.$message({
          message: "请选择数据库",
          type: "warning",
        });
      }
    },
    deleteDbTableRData(data) {
      this.dbTableRData.splice(data.index, 1);
    },

    validateSteps() {
      return new Promise((resolve) => {
        if (this.stepActive == 0) {
          // 判断基础信息是否填写完整
          this.validateBaseInfo().then((res) => {
            resolve(res);
          });
        } else {
          resolve(true);
        }
      });
    },
    steps(num) {
      return this.stepActive == num;
    },
    validateBaseInfo() {
      return new Promise((resolve) => {
        this.$refs.baseInfo.validate((valid) => {
          if (valid) {
            if (this.formData.f_FormType == 2) {
              resolve(true);
              return;
            }
            if (this.isNotFetchTables) {
              this.$message({
                type: "error",
                message:
                  "请将数据表的对象导入,点击数据表添加按钮,导入表重新编辑页面!",
              });
              resolve(false);
              return;
            }

            if (this.dbTableData.length > 0) {
              if (this.formData.f_FormType != 1) {
                if (
                  this.dbTableData.find(
                    (t) =>
                      t.type != "main" &&
                      (this.$validatenull(t.field) ||
                        this.$validatenull(t.relationName) ||
                        this.$validatenull(t.relationField))
                  ) != undefined
                ) {
                  this.$message({
                    type: "error",
                    message: "请完善数据库表信息!",
                  });
                  resolve(false);
                  return;
                }
              } else {
                if (
                  this.dbTableData.find(
                    (t) =>
                      t.type != "main" && this.$validatenull(t.relationField)
                  ) != undefined
                ) {
                  this.$message({
                    type: "error",
                    message: "请完善子试图和主视图关联!",
                  });
                  resolve(false);
                  return;
                }
              }
            } else {
              this.$message({
                type: "error",
                message:
                  this.formData.f_FormType != 1
                    ? "请添加数据库表!"
                    : "请添加视图语句",
              });
              resolve(false);
              return;
            }

            if (this.dbTableRData.length > 0) {
              if (
                this.dbTableRData.find(
                  (t) =>
                    this.$validatenull(t.fname) ||
                    this.$validatenull(t.cfield) ||
                    this.$validatenull(t.field) ||
                    this.$validatenull(t.relationName) ||
                    this.$validatenull(t.relationField)
                ) != undefined
              ) {
                this.$message({
                  type: "error",
                  message: "请完善数据库关联表信息!",
                });
                resolve(false);
                return;
              }
            }

            this.$nextTick(() => {
              this.$refs.formDesign.updateTable();
            });

            resolve(true);
          } else {
            resolve(false);
          }
        });
      });
    },
    resetForm() {
      this.$refs.formDesign.clear();
      this.$formClear(this.$refs.baseInfo);
      this.isNotFetchTables = false;
      this.dbTableData = [];
      this.dbTableRData = [];
      this.tableColumns = {};
      this.mainTableName = ""
    },
    validateForm() {
      return this.$refs.formDesign.validate();
    },
    async setForm(id, formCopy) {
      const data = await this.$awaitWraper(apiScheme.get(id));
      if (data) {
        if (formCopy) {
          data.info.f_Id = "";
          data.info.f_SchemeId = "";
          data.info.f_Name = `${data.info.f_Name}-复制`;
          data.scheme.f_Id = "";
          data.scheme.f_SchemeInfoId = "";
        }
        let scheme = JSON.parse(data.scheme.f_Scheme);
        data.info.f_DbCode = scheme.dbCode;
        this.formData = data.info;
        this.dbTableData = scheme.db;
        this.dbTableRData = scheme.rdb || [];

        if (this.formData.f_FormType != 1 && this.formData.f_FormType != 2) {
          let tableNames = [];
          tableNames.push(...this.dbTableData.map((t) => t.name));
          tableNames.push(...this.dbTableRData.map((t) => t.name));

          tableNames = this.$unique(tableNames);
          // 加载表数据
          const codeTables = await this.$awaitWraper(
            apiCodeTable.getList(scheme.dbCode, String(tableNames))
          );
          // 新版本加入数据模型这个概念，表单设计模版里不保存列的信息
          // 当数据对象被改变时会直接影响到表单
          if (codeTables.length < tableNames.length) {
            // 表示部分数据表没有加载到，需要导入或添加
            this.isNotFetchTables = true;
          } else {
            const tableList = [...this.dbTableData, ...this.dbTableRData];
            for (const table of tableList) {
              const codeTable = codeTables.find(
                (t) => t.lr_db_codetableEntity.f_TableName == table.name
              );

              table.columns = codeTable.lr_db_codecolumnsList.map((t) => ({
                name: t.f_DbColumnName,
                csType: t.f_CsType,
                isIdentity: t.f_IsIdentity == 1,
                isPrimary: t.f_IsPrimaryKey == 1,
                isNullable: t.f_IsNullable == 1,
                coment: t.f_Description,
              }));

              this.tableColumns[table.name] = table.columns;
            }
          }
        }
        this.$refs.formDesign.setData(scheme.formInfo);
        const obj = scheme.db.filter((t) => t.type == "main")[0];
        obj ? (this.mainTableName = obj.name) : "";
        return true;
      } else {
        this.$message({
          message: "数据加载失败",
          type: "warning",
        });

        return false;
      }
    },
    getForm(isDraft, isAutoCreateTable, dataInfo) {
      let db = [];
      const rdb = [];
      let primaryKey = []; // 调整支持多主键 2022/11/30
      if (this.formData.f_FormType != 1 && this.formData.f_FormType != 2) {
        // 普通表单
        const mainTable = this.dbTableData.find((t) => t.type == "main");

        // 调整支持多主键 2022/11/30
        mainTable.columns.forEach((column) => {
          if (column.isPrimary) {
            primaryKey.push(column.name);
          }
        });
      }

      const dbTableData = this.$deepClone(this.dbTableData);
      const dbTableRData = this.$deepClone(this.dbTableRData);

      for (const item of dbTableData) {
        if (this.formData.f_FormType != 1) {
          delete item.columns;
        }
        db.push(item);
      }
      for (const item of dbTableRData) {
        if (this.formData.f_FormType != 1) {
          delete item.columns;
        }
        rdb.push(item);
      }

      if (isAutoCreateTable) {
        db = [];
        const formInfo = dataInfo.formInfo;
        const table = {
          id: formInfo.tableInfo.tableName,
          name: formInfo.tableInfo.tableName,
          comment: formInfo.tableInfo.tableNotes,
          type: "main",
        };
        db.push(table);
        dataInfo.tableData.map((item, index) => {
          if (index != 0) {
            const obj = {
              id: item.table,
              name: item.table,
              comment: item.tableNotes,
              type: "chlid",
              field: `${formInfo.tableInfo.tableName}_Id`,
              relationName: formInfo.tableInfo.tableName,
              relationField: "F_Id",
            };
            db.push(obj);
          }
        });
      }
      let scheme = {
        dbCode: this.formData.f_DbCode,
        db: db,
        rdb: rdb,
        primaryKey: isAutoCreateTable ? "F_Id" : String(primaryKey),
        formInfo: isAutoCreateTable
          ? dataInfo.formInfo
          : this.$refs.formDesign.getData(),
        formType: this.formData.f_FormType,
      };
      let postData = {
        info: this.$deepClone(this.formData),
        scheme: {
          F_Scheme: JSON.stringify(scheme),
          F_Type: isDraft ? 2 : 1,
        },
      };
      return postData;
    },

    handleFormTypeChange() {
      this.dbTableData = [];
      this.dbTableRData = [];
    },

    addSqlData() {
      // 添加试图语句
      if (this.formData.f_DbCode) {
        this.editSql = false;
        this.sqlDialogTitle = "添加SQL";
        this.addSqlDialog = true;
      } else {
        this.$message({
          message: "请选择数据库",
          type: "warning",
        });
      }
    },
    editSqlData(row) {
      if (this.formData.f_DbCode) {
        this.editSql = true;
        this.sqlDialogRow = row;
        this.sqlDialogTitle = "编辑SQL";
        this.addSqlDialog = true;
      } else {
        this.$message({
          message: "请选择数据库",
          type: "warning",
        });
      }
    },
    deleteSqlData({ index, row }) {
      // 删除试图语句
      if (row.type != "main") {
        this.dbTableData.splice(index, 1);
      } else {
        this.$message({
          message: "主语句无法删除",
          type: "warning",
        });
      }
    },
    async sqlDialogSave(showLoading, hideLoading) {
      showLoading("保存中...");
      if (await this.$refs.sqlForm.validateForm()) {
        const data = this.$refs.sqlForm.getForm();
        if (this.dbTableData.length != 0 && data.type != "main") {
          if (data.sql.indexOf("@param") == -1) {
            this.$message({
              message: "请在语句中设置关联参数",
              type: "warning",
            });
            hideLoading();
            return;
          }
        }

        // 加载列字段
        const list = await this.$awaitWraper(
          apiScheme.geColnames(this.formData.f_DbCode, data.sql)
        );
        if (list == null) {
          hideLoading();
          return;
        }
        data.columns = list.map((t) => {
          return { name: t };
        });

        if (this.editSql) {
          const index = this.dbTableData.findIndex((t) => (t.id = data.id));
          this.$set(this.dbTableData, index, data);
        } else {
          if (this.dbTableData.length == 0) {
            data.type = "main";
          } else {
            data.type = "chlid";
          }
          data.id = this.$uuid();
          this.dbTableData.push(data);
        }

        this.addSqlDialog = false;
      }

      hideLoading();
    },
    sqlDialogClosed() {
      this.$refs.sqlForm.resetForm();
    },
    sqlDialogOpened() {
      if (this.editSql) {
        this.$refs.sqlForm.setForm(this.sqlDialogRow);
      } else {
        this.$refs.sqlForm.resetSql();
      }
    },
  },
};
</script>
